package org.jasig.cas.ext.pac4j.plugin.qq;

import com.fasterxml.jackson.databind.JsonNode;
import org.jasig.cas.ext.pac4j.plugin.profile.OAuthAttributesDefinitions;
import org.pac4j.core.client.BaseClient;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.exception.HttpCommunicationException;
import org.pac4j.oauth.client.BaseOAuth20Client;
import org.pac4j.oauth.credentials.OAuthCredentials;
import org.pac4j.oauth.profile.JsonHelper;
import org.pac4j.oauth.profile.OAuth20Profile;
import org.scribe.exceptions.OAuthException;
import org.scribe.model.*;

import java.util.List;

/**
 * Created by rain.wen on 2016/9/2.
 */
public class QqClient extends BaseOAuth20Client<QqProfile> {


    @Override
    protected boolean requiresStateParameter() {
        return false;
    }

    @Override
    protected boolean hasBeenCancelled(WebContext webContext) {
        return false;
    }

    @Override
    protected String getProfileUrl() {
        return QqApi20.BASE_URL + "user/get_user_info";
    }

    /**
     * 返回获取用户 openid url
     *
     * @return 获取用户 openid url
     */
    protected String getOpenIdUrl() {
        return QqApi20.BASE_URL + "oauth2.0/me";
    }

    @Override
    protected QqProfile extractUserProfile(String body) {
        final QqProfile profile = new QqProfile();
        JsonNode json = JsonHelper.getFirstNode(body);
        if (json != null) {
            List<String> principalAttributes = OAuthAttributesDefinitions.qqDefinition
                    .getPrincipalAttributes();
            for (final String name : principalAttributes) {
                Object value = JsonHelper.get(json, name);
                profile.addAttribute(name, value);

                if (QqAttributesDefinition.NICKNAME.equals(name) == true) {
                    profile.addAttribute(QqAttributesDefinition.USERNAME, value);
                }
                if(QqAttributesDefinition.FIGUREURL_QQ_1.equals(name) == true){
                    profile.addAttribute(QqAttributesDefinition.PICTURE_URL, value);
                }
                if(QqAttributesDefinition.FIGUREURL_QQ_2.equals(name) == true){
                    profile.addAttribute(QqAttributesDefinition.PICTURE_URL, value);
                }
            }
        }
        return profile;
    }

    /**
     * 重写获取QQ用户信息的请求
     * WIKI 说明 http://wiki.connect.qq.com/openapi%E8%B0%83%E7%94%A8%E8%AF%B4%E6%98%8E_oauth2-0
     */
    @Override
    protected QqProfile retrieveUserProfileFromToken(Token accessToken) {
        String openIdUrl = getOpenIdUrl();
        logger.debug("get openid from: " + openIdUrl);
        String openIdBody = sendRequestForData(accessToken, openIdUrl);
        if (openIdBody == null) {
            return null;
        }

        String str = openIdBody.replace("callback( ", "").replace(" );", "");

        JsonNode json = JsonHelper.getFirstNode(str);
        JsonNode clientId = json.get("client_id");
        JsonNode openId = json.get("openid");

        if (openId == null) {
            throw new OAuthException(
                    "Response body is incorrect. Can't extract a openid from this: '" + openIdBody + "'",
                    null);
        }

        String url = getProfileUrl() + "?oauth_consumer_key=" + clientId.textValue() + "&openid="
                + openId.textValue();
        logger.debug("get user profile by clientid<" + clientId + "> and openid<" + openId
                + "> from: " + url);

        String body = this.sendRequestForData(accessToken, url);
        if (body == null) {
            throw new HttpCommunicationException("Not data found for accessToken : " + accessToken);
        } else {
            QqProfile profile = this.extractUserProfile(body);
            profile.setId(openId.textValue());
            this.addAccessTokenToProfile(profile, accessToken);
            return profile;
        }
    }

    @Override
    protected BaseClient<OAuthCredentials, QqProfile> newClient() {
        return new QqClient();
    }

    @Override
    protected void internalInit() {
        super.internalInit();
        QqApi20 api = new QqApi20();
        this.service = new QqOAuth20ServiceImpl(api, new OAuthConfig(this.key, this.secret, this.callbackUrl, SignatureType.Header, null, null),
                this.connectTimeout, this.readTimeout, this.proxyHost, this.proxyPort);
    }
}
